package ast.statement.select

import ast.expr.SqlBinaryExpr
import ast.expr.SqlBinaryOperator
import ast.expr.SqlExpr
import ast.expr.SqlIdentifierExpr
import ast.limit.SqlLimit
import ast.order.SqlOrderBy
import ast.statement.SqlStatement
import ast.table.SqlTableSource

/**
 * sql语法树：查询语句父类
 */
sealed class SqlSelectQuery : SqlStatement

/**
 * sql语法树：普通查询语句
 * @property distinct Boolean 是否去重
 * @property selectList MutableList<SqlSelectItem> 查询项列表
 * @property from SqlTableSource? 查询的表
 * @property where SqlExpr? 查询条件子句
 * @property groupBy MutableList<SqlExpr> 分组规则列表
 * @property orderBy MutableList<SqlOrderBy> 排序规则列表
 * @property forUpdate Boolean 是否生成FOR UPDATE
 * @property limit SqlLimit? 限制子句
 * @property having SqlExpr? 聚合筛选条件子句
 */
data class SqlSelect(
    var distinct: Boolean = false,
    val selectList: MutableList<SqlSelectItem> = mutableListOf(),
    var from: SqlTableSource? = null,
    var where: SqlExpr? = null,
    val groupBy: MutableList<SqlExpr> = mutableListOf(),
    val orderBy: MutableList<SqlOrderBy> = mutableListOf(),
    var forUpdate: Boolean = false,
    var limit: SqlLimit? = null,
    var having: SqlExpr? = null
) : SqlSelectQuery() {
    /**
     * 添加查询项
     * @param expr SqlExpr 查询的表达式
     * @param alias String? 别名
     */
    fun addSelectItem(expr: SqlExpr, alias: String? = null) {
        selectList.add(SqlSelectItem(expr, alias))
    }

    /**
     * 添加查询项
     * @param column String 查询的字段名
     * @param alias String? 别名
     */
    fun addSelectItem(column: String, alias: String? = null) {
        selectList.add(SqlSelectItem(SqlIdentifierExpr(column), alias))
    }

    /**
     * 添加合取查询条件
     * @param condition SqlExpr 条件表达式
     */
    fun addCondition(condition: SqlExpr) {
        where = if (where != null) {
            SqlBinaryExpr(where!!, SqlBinaryOperator.AND, condition)
        } else {
            condition
        }
    }

    /**
     * 添加合取聚合筛选条件
     * @param condition SqlExpr 条件表达式
     */
    fun addHaving(condition: SqlExpr) {
        having = if (having != null) {
            SqlBinaryExpr(having!!, SqlBinaryOperator.AND, condition)
        } else {
            condition
        }
    }
}

/**
 * sql语法树：UNION查询语句
 * @property left SqlSelectQuery 左侧查询语句
 * @property type SqlUnionType 合并类型枚举
 * @property right SqlSelectQuery 右侧查询语句
 */
data class SqlUnionSelect(val left: SqlSelectQuery, val type: SqlUnionType, val right: SqlSelectQuery) :
    SqlSelectQuery()

/**
 * sql语法树：WITH查询语句
 * @property with MutableList<SqlWithItem> 引述子查询列表
 * @property recursive Boolean 是否是递归查询（MYSQL和PGSQL用）
 * @property query SqlSelectQuery? 最终的查询语句
 */
data class SqlWithSelect(
    val with: MutableList<SqlWithItem> = mutableListOf(),
    var recursive: Boolean = false,
    var query: SqlSelectQuery? = null
) : SqlSelectQuery()

/**
 * sql语法树：VALUES查询语句（用于生成临时表）
 * @property values MutableList<List<SqlExpr>> VALUES列表
 */
data class SqlValuesSelect(val values: MutableList<List<SqlExpr>> = mutableListOf()) : SqlSelectQuery()